﻿/**
 * 转表编辑器
 */

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using Excel;
using System.Data;
using System;
using System.Text;
using Base.Utils;
using Base.Debug;
using System.Text.RegularExpressions;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using ProtoBuf;
using System.Reflection;

public class SheetEditor
{
    private const string SHEETROOTPATH = "Excels/xlsx";
    private const string SHEETEXT = ".xlsx";
    private static string OUTSHEETCSPATH = "Assets/HotUpdate/Sheet/SheetProtobuf.cs";
    private static string OUTSHEETMANAGERPATH = "Assets/HotUpdate/Sheet/SheetManager.cs";
    private static string OUTSHEETBYTES = "Assets/Prefabs/Bytes/{0}.bytes";
    private static string OUTEXCELPROTO = "..\\Server\\proto\\";
    private static string OUTSHEETBYTES_client = "Assets/Prefabs/Bytes_client/{0}.bytes";
    /// <summary>
    /// 默认情况下，表格只需导出以id为key的字典。特殊情况下，要在下面自定义key和导出数据的类型
    /// </summary>
    private static readonly Dictionary<string, SheetExportBase> mSheetExportConst = new Dictionary<string, SheetExportBase>
    {
        { "Example", new SheetExportBase("Example").SetKey("exampleInt") },
        { "Preload", new SheetExportBase("Preload").SetExportDataType(EExportDataType.ONLY_ARRAY) }
    };

    /// <summary>
    /// 枚举类型存储地方
    /// </summary>
    private static Dictionary<string, HashSet<string>> mSheetEnumDict = new Dictionary<string, HashSet<string>>();

    [MenuItem("Tools/Sheet/ExportBytes")]
    private static void ExportBytes()
    {
        mSheetEnumDict.Clear();
        var sheetDir = new DirectoryInfo(SHEETROOTPATH);
        var files = sheetDir.GetFiles();
        var sheetDict = new Dictionary<string, DataTable>();

        //------------------------------生成CS--------------------------------
        var sheetCSSB = new StringBuilder();
        sheetCSSB.Append(LineText("/**"));
        sheetCSSB.Append(LineText(" * Tool generation, do not modify!!!"));
        sheetCSSB.Append(LineText(" */\n"));
        sheetCSSB.Append(LineText("using ProtoBuf;\nusing System.IO;\nusing System.Collections.Generic;\n"));
        sheetCSSB.Append(LineText("namespace Sheet"));
        sheetCSSB.Append(LineText("{"));
        sheetCSSB.Append(LineText(GetBaseArrayCode()));
        for (var i = 0; i < files.Length; i++)
        {
            var file = files[i];
            EditorUtility.DisplayProgressBar("Generate Protobuf CS", file.FullName, 1.0f * (i + 1) / files.Length);
            if (file.Extension != SHEETEXT) continue;
            var name = file.Name.Replace(SHEETEXT, "");
            sheetCSSB.Append(LineText("[ProtoContract]", 1));
            sheetCSSB.Append(LineText("public class " + name, 1));
            sheetCSSB.Append(LineText("{", 1));
            var dataSet = GetDataSet(file.FullName);
            var table = dataSet.Tables[0];
            sheetDict.Add(name, table);
            var cols = table.Columns.Count;
            var count = 0;
            for (var j = 0; j < cols; j++)
            {
                var row0 = table.Rows[0][j].ToString();
                if (FilterKey(row0, "client"))
                {
                    count++;
                    var row1 = table.Rows[1][j].ToString();
                    var row2 = table.Rows[2][j].ToString();
                    sheetCSSB.Append(LineText(string.Format("[ProtoMember({0})]", count), 2));
                    if (row1.StartsWith("array"))
                    {
                        var reg = new Regex("<(.*)>");
                        var match = reg.Match(row1);
                        var value = match.Groups[1].Value;
                        sheetCSSB.Append(LineText(string.Format("public List<{0}> {1} = new List<{0}>();", value, row2), 2));
                    }
                    else
                    {
                        sheetCSSB.Append(LineText(string.Format("public {0} {1};", row1, row2), 2));
                    }
                    if (row1.EndsWith("Enum"))
                    {
                        if (!mSheetEnumDict.ContainsKey(row1)) mSheetEnumDict.Add(row1, new HashSet<string>());
                        for (int k = 4; k < table.Rows.Count; k++)
                        {
                            var enumStr = table.Rows[k][j].ToString();
                            if (!mSheetEnumDict[row1].Contains(enumStr))
                            {
                                mSheetEnumDict[row1].Add(enumStr);
                            }
                        }
                    }
                }
            }
            sheetCSSB.Append(LineText("}\n", 1));
            sheetCSSB.Append(LineText("[ProtoContract]", 1));
            sheetCSSB.Append(LineText("public class " + name + "List : BaseList", 1));
            sheetCSSB.Append(LineText("{", 1));
            sheetCSSB.Append(LineText("[ProtoMember(1)]", 2));
            sheetCSSB.Append(LineText(string.Format("public List<{0}> Items = new List<{0}>();", name), 2));
            sheetCSSB.Append(LineText("}\n", 1));
        }
        //添加枚举
        foreach (var sheetEnum in mSheetEnumDict)
        {
            sheetCSSB.Append(LineText("public enum " + sheetEnum.Key, 1));
            sheetCSSB.Append(LineText("{", 1));
            foreach (var sheetEnumKey in sheetEnum.Value)
            {
                sheetCSSB.Append(LineText(sheetEnumKey + ",", 2));
            }
            sheetCSSB.Append(LineText("Max", 2));
            sheetCSSB.Append(LineText("}\n", 1));
        }
        sheetCSSB.Append(LineText("}"));
        Base.Utils.FileUtil.WriteAllText(OUTSHEETCSPATH, sheetCSSB.ToString());
        Debugger.Log("Generate Protobuf CS Done!");

        //------------------------------生成SheetManager------------------------------
        var sheetManagerSB = new StringBuilder();
        sheetManagerSB.Append(LineText("/**"));
        sheetManagerSB.Append(LineText(" * Tool generation, do not modify!!!"));
        sheetManagerSB.Append(LineText(" */\n"));
        sheetManagerSB.Append(LineText("using Sheet;" +
            "\nusing System.Collections.Generic;" +
            "\nusing UnityEngine;" +
            "\nusing Base.Utils; \n"));
        sheetManagerSB.Append(LineText("public partial class SheetManager : Singleton<SheetManager>"));
        sheetManagerSB.Append(LineText("{"));

        string str = "\n";
        var sheetCount = 0;
        foreach (var table in sheetDict)
        {
            sheetCount++;
            var sheetName = table.Key;
            EditorUtility.DisplayProgressBar("Generate SheetManager", sheetName, 1.0f * sheetCount / sheetDict.Count);
            SheetExportBase sheetExportBase;
            if (!mSheetExportConst.TryGetValue(sheetName, out sheetExportBase))
            {
                sheetExportBase = new SheetExportBase(sheetName);
            }
            sheetExportBase.SetKey(table.Value.Rows[2][0].ToString());
            string exportText = sheetExportBase.ExportScript();
            sheetManagerSB.Append(exportText);
            str+= sheetExportBase.Exportinit();
        }
        sheetManagerSB.Append(LineText("\n"));
        //初始化表
        sheetManagerSB.Append(LineText("public void initAllSheet(){",1));
        sheetManagerSB.Append(str);
        sheetManagerSB.Append(LineText("}",1));
        sheetManagerSB.Append(LineText("}"));
        Base.Utils.FileUtil.WriteAllText(OUTSHEETMANAGERPATH, sheetManagerSB.ToString());
        Debugger.Log("Generate SheetManager Done!");

        //------------------------------生成bytes-------------------------------------
        var provider = new CSharpCodeProvider();
        var parameters = new CompilerParameters();
        parameters.ReferencedAssemblies.Add(Application.dataPath + "/Plugins/Protobuf/protobuf-net.dll");
#if UNITY_EDITOR_OSX
        var pathName = "PATH";
        var envPath = Environment.GetEnvironmentVariable(pathName);
        var monoPath = Path.Combine(EditorApplication.applicationContentsPath, "Mono/bin");
        Environment.SetEnvironmentVariable(pathName, envPath + ":" + monoPath, EnvironmentVariableTarget.Process);
#endif
        var result = provider.CompileAssemblyFromSource(parameters, sheetCSSB.ToString());
        if (result.Errors.Count == 0)
        {
            Debugger.Log("SheetProtobuf Build Success!");
            var ass = result.CompiledAssembly;
            sheetCount = 0;
            foreach(var table in sheetDict)
            {
                sheetCount++;
                var name = table.Key;
                var data = table.Value;
                EditorUtility.DisplayProgressBar("Generate Bytes", name, 1.0f * sheetCount / sheetDict.Count);
                var listObj = ass.CreateInstance("Sheet." + name + "List");
                var list = listObj.GetType().GetField("Items").GetValue(listObj);
                var addMethod = list.GetType().GetMethod("Add");
                var rows = data.Rows.Count;
                var cols = data.Columns.Count;
                for (var i = 4; i < rows; i++)
                {
                    var obj = ass.CreateInstance("Sheet." + name);
                    var type = obj.GetType();
                    for (var j = 0; j < cols; j++)
                    {
                        var row0 = data.Rows[0][j].ToString();
                        if (!FilterKey(row0, "client")) continue;
                        var row1 = data.Rows[1][j].ToString();
                        var row2 = data.Rows[2][j].ToString();
                        var value = data.Rows[i][j];
                        if (row1.StartsWith("array"))
                        {
                            var reg = new Regex("<(.*)>");
                            var match = reg.Match(row1);
                            var valueType = match.Groups[1].Value;
                            var arrayValue = obj.GetType().GetField(row2).GetValue(obj);
                            var valueStr = value.ToString();
                            valueStr = valueStr.Substring(1, valueStr.Length - 2);
                            var valueList = valueStr.Split(',');
                            for (var k = 0; k < valueList.Length; k++)
                            {
                                switch (valueType)
                                {
                                    case "int":
                                        ((List<int>)arrayValue).Add(Convert.ToInt32(valueList[k]));
                                        break;
                                    case "float":
                                        ((List<float>)arrayValue).Add(Convert.ToSingle(valueList[k]));
                                        break;
                                    case "string":
                                        ((List<string>)arrayValue).Add(valueList[k]);
                                        break;
                                    case "bool":
                                        ((List<bool>)arrayValue).Add(Convert.ToBoolean(valueList[k]));
                                        break;
                                }
                            }
                        }
                        else if (row1.EndsWith("Enum"))
                        {
                            var enumInst = ass.CreateInstance("Sheet." + row1);
                            type.GetField(row2).SetValue(obj, (int)Enum.Parse(enumInst.GetType(), Convert.ToString(value)));
                        }
                        else
                        {
                            SetValue(type, row1, row2, obj, value, i, j, name);
                        }  
                    }

                    addMethod.Invoke(list, new object[] { obj });
                }
                var exportMethod = listObj.GetType().GetMethod("Export");
                var outFile = string.Format(OUTSHEETBYTES, name);
                if (Base.Utils.FileUtil.CheckFileAndCreateDirWhenNeeded(outFile))
                {
                    exportMethod.Invoke(listObj, new object[] { outFile });
                }
            }
            Debugger.Log("Generate Bytes Done!");
        }
        else
        {
            Debugger.LogError("SheetProtobuf Build Failed!");
        }
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }

    /// <summary>
    /// 过滤列
    /// </summary>
    /// <param name="key">列标志</param>
    /// <param name="target">导出目标</param>
    private static bool FilterKey(string key, string target)
    {
        return (!string.IsNullOrEmpty(key)) && (key.Equals("-") || key.Equals(target, StringComparison.OrdinalIgnoreCase));
    }

    /// <summary>
    /// Sets the value.
    /// </summary>
    private static void SetValue(Type type, string key1, string key2, object obj, object value, int row, int col, string name)
    {
        try
        {
            switch (key1)
            {
                case "int":
                    type.GetField(key2).SetValue(obj, Convert.ToInt32(value));
                    break;
                case "float":
                    type.GetField(key2).SetValue(obj, Convert.ToSingle(value));
                    break;
                case "string":
                    type.GetField(key2).SetValue(obj, Convert.ToString(value));
                    break;
                case "bool":
                    if (value.ToString().Equals("true", StringComparison.OrdinalIgnoreCase))
                    {
                        type.GetField(key2).SetValue(obj, true);
                    }
                    else
                    {
                        type.GetField(key2).SetValue(obj, false);
                    }
                    break;
            }
        }
        catch(Exception e)
        {
            Debugger.LogError(e.Message);
            Debugger.LogError("[{0}] [{1}] [ROW]:{2} [COL]:{3}", name, key1, row + 1, Convert.ToChar(col + 'A'));
        }
    }


    private static void SetValue2(Type type, string key1, string key2, object obj, object value, int row, int col, string name)
    {
        try
        {
            switch (key1)
            {
                case "int32":
                    type.GetProperty(key2).SetValue(obj, Convert.ToInt32(value));
                    break;
                case "float":
                    type.GetProperty(key2).SetValue(obj, Convert.ToSingle(value));
                    break;
                case "string":
                    Debug.Log(type.GetProperty(key2).Name);
                    type.GetProperty(key2).SetValue(obj, Convert.ToString(value));
                    break;
                case "bool":
                    if (value.ToString().Equals("true", StringComparison.OrdinalIgnoreCase))
                    {
                        type.GetProperty(key2).SetValue(obj, true);
                    }
                    else
                    {
                        type.GetProperty(key2).SetValue(obj, false);
                    }
                    break;
            }
        }
        catch (Exception e)
        {
            Debugger.LogError(e.Message);
            Debugger.LogError("[{0}] [{1}] [ROW]:{2} [COL]:{3}", name, key1, row + 1, Convert.ToChar(col + 'A'));
        }
    }
    /// <summary>
    /// 获得每一行的字符串
    /// </summary>
    public static string LineText(string text, int tabCount = 0)
    {
        string ret = "";
        for (int i = 1; i <= tabCount; i++)
        {
            ret = StringUtil.Concat("\t", ret);
        }
        ret = StringUtil.Concat(ret, text);
        ret = StringUtil.Concat(ret, "\n");
        return ret;
    }

    /// <summary>
    /// Gets the base array code.
    /// </summary>
    private static string GetBaseArrayCode()
    {
        return @"    public class BaseList
    {
        public void Export(string outFile)
        {
            using (MemoryStream m = new MemoryStream())
            {
                Serializer.Serialize(m, this);
                m.Position = 0;
                int length = (int)m.Length;
                var buffer = new byte[length];
                m.Read(buffer, 0, length);
                File.WriteAllBytes(outFile, buffer);
            }
        }
    }
    ";
    }

    /// <summary>
    /// excelReader.AsDataSet() 会因为表内有空值而报错
    /// </summary>
    public static DataSet GetDataSet(string path)
    {
        var stream = File.Open(path, FileMode.Open, FileAccess.Read);
        var excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
        var ds = new DataSet();
        do
        {
            DataTable dt = GetTable(excelReader);
            ds.Merge(dt);
        } while (excelReader.NextResult());
        excelReader.Close();
        excelReader.Dispose();
        stream.Close();
        stream.Dispose();
        return ds;
    }

    /// <summary>
    /// 获得表格数据
    /// </summary>
    private static DataTable GetTable(IExcelDataReader excelReader)
    {
        DataTable dt = new DataTable();
        dt.TableName = excelReader.Name;

        bool isInit = false;
        string[] ItemArray = null;
        while (excelReader.Read())
        {
            if (!isInit)
            {
                isInit = true;
                for (int i = 0; i < excelReader.FieldCount; i++)
                {
                    dt.Columns.Add("", typeof(string));
                }
                ItemArray = new string[excelReader.FieldCount];
            }

            if (excelReader.IsDBNull(0))
            {
                continue;
            }
            for (int i = 0; i < excelReader.FieldCount; i++)
            {
                string value = excelReader.IsDBNull(i) ? "" : excelReader.GetString(i);
                ItemArray[i] = value;
            }
            dt.Rows.Add(ItemArray);
        }
        return dt;
    }


    [MenuItem("Tools/Sheet/导出excel proto")]
    private static void ExportExcelProto()
    {
        mSheetEnumDict.Clear();
        var sheetDir = new DirectoryInfo(SHEETROOTPATH);
        var files = sheetDir.GetFiles();
        var sheetDict = new Dictionary<string, DataTable>();

        //------------------------------生成proto--------------------------------
        var sheetCSSB = new StringBuilder();
    
        for (var i = 0; i < files.Length; i++)
        {
            sheetCSSB.Clear();
            var file = files[i];
            EditorUtility.DisplayProgressBar("Generate Protobuf CS", file.FullName, 1.0f * (i + 1) / files.Length);
            if (file.Extension != SHEETEXT) continue;
            var name = file.Name.Replace(SHEETEXT, "");
            var upname = name.ToUpper();
            sheetCSSB.Append(LineText("syntax = \"proto3\";\n", 0));
            sheetCSSB.Append(LineText("package TABLE;\n", 0));
            sheetCSSB.Append(LineText("message " + upname + "", 0));
            sheetCSSB.Append(LineText("{\n", 0));
            var dataSet = GetDataSet(file.FullName);
            var table = dataSet.Tables[0];
            sheetDict.Add(upname, table);
            var cols = table.Columns.Count;
            var count = 0;
            for (var j = 0; j < cols; j++)
            {
                var row0 = table.Rows[0][j].ToString();
                if (FilterKey(row0, "client"))
                {
                    count++;
                    var row1 = table.Rows[1][j].ToString();
                    var row2 = table.Rows[2][j].ToString();
                    var row3 = table.Rows[3][j].ToString();
                    if (row1.StartsWith("array"))
                    {
                        var reg = new Regex("<(.*)>");
                        var match = reg.Match(row1);
                        var value = match.Groups[1].Value;
                        sheetCSSB.Append(LineText(string.Format("repeated {0} {1} = {2};//{3}", value, row2,j+1,row3), 1));
                    }
                    else
                    {
                        sheetCSSB.Append(LineText(string.Format("{0} {1}={2};//{3}", row1, row2,j+1,row3), 1));
                    }
                    
                }
            }
            sheetCSSB.Append(LineText("}\n", 0));
            sheetCSSB.Append(LineText("message " + upname + "ARRAY", 0));
            sheetCSSB.Append(LineText("{\n", 0));
            sheetCSSB.Append(LineText("repeated "+ upname + " rows=1;", 1));
          
            sheetCSSB.Append(LineText("}\n", 0));
            var path = $"{Application.dataPath}/../Server/Clientproto/{name}.proto";
            Base.Utils.FileUtil.WriteAllText(path, sheetCSSB.ToString());
        }

        Debugger.Log("Generate Protobuf CS Done!");

     
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }


    [MenuItem("Tools/Sheet/导出excel sheetmanager.cs")]
    private static void ExportExcelSheetmanager()
    {
        var sheetDict = new Dictionary<string, DataTable>();
        var sheetDir = new DirectoryInfo(SHEETROOTPATH);
        var files = sheetDir.GetFiles();

        for (var i = 0; i < files.Length; i++)
        {
            var file = files[i];
            EditorUtility.DisplayProgressBar("Generate Protobuf CS", file.FullName, 1.0f * (i + 1) / files.Length);
            if (file.Extension != SHEETEXT) continue;
            var name = file.Name.Replace(SHEETEXT, "");
            var dataSet = GetDataSet(file.FullName);
            var table = dataSet.Tables[0];
            sheetDict.Add(name, table);

        }
        //------------------------------生成SheetManager------------------------------
        var sheetManagerSB = new StringBuilder();
        sheetManagerSB.Append(LineText("/**"));
        sheetManagerSB.Append(LineText(" * Tool generation, do not modify!!!"));
        sheetManagerSB.Append(LineText(" */\n"));
        sheetManagerSB.Append(LineText("using ProtoBuf;" +
            "\nusing System.Collections.Generic;" +
            "\nusing UnityEngine;" +
            "\nusing Table;" +
            "\nusing Base.Utils; \n"));
        sheetManagerSB.Append(LineText("public partial class SheetManager : Singleton<SheetManager>"));
        sheetManagerSB.Append(LineText("{"));

        string str = "\n";
        var sheetCount = 0;
        foreach (var table in sheetDict)
        {
            sheetCount++;
            var sheetName = table.Key;
            EditorUtility.DisplayProgressBar("Generate SheetManager", sheetName, 1.0f * sheetCount / sheetDict.Count);
            SheetExportBase sheetExportBase;
            if (!mSheetExportConst.TryGetValue(sheetName, out sheetExportBase))
            {
                sheetExportBase = new SheetExportBase(sheetName);
            }
            sheetExportBase.SetKey(table.Value.Rows[2][0].ToString());
            string exportText = sheetExportBase.ExportScript();
            sheetManagerSB.Append(exportText);
            str += sheetExportBase.Exportinit();
        }
        sheetManagerSB.Append(LineText("\n"));
        //初始化表
        sheetManagerSB.Append(LineText("public void initAllSheet(){", 1));
        sheetManagerSB.Append(str);
        sheetManagerSB.Append(LineText("}", 1));
        sheetManagerSB.Append(LineText("}"));
        Base.Utils.FileUtil.WriteAllText(OUTSHEETMANAGERPATH, sheetManagerSB.ToString());
        Debugger.Log("Generate SheetManager Done!");

        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }


    [MenuItem("Tools/Sheet/导出excel bytes数据")]
    private static void ExportExcelBytes()
    {
        var sheetDict = new Dictionary<string, DataTable>();
        var sheetDir = new DirectoryInfo(SHEETROOTPATH);
        var files = sheetDir.GetFiles();

        for (var i = 0; i < files.Length; i++)
        {
            var file = files[i];
            EditorUtility.DisplayProgressBar("Generate Protobuf CS", file.FullName, 1.0f * (i + 1) / files.Length);
            if (file.Extension != SHEETEXT) continue;
            var name = file.Name.Replace(SHEETEXT, "");
            var dataSet = GetDataSet(file.FullName);
            var table = dataSet.Tables[0];
            sheetDict.Add(name, table);
          
        }
        //------------------------------生成bytes-------------------------------------
        var sheetCount = 0;
        foreach (var table in sheetDict)
        {
            sheetCount++;
            var name = table.Key;
            var data = table.Value;
            EditorUtility.DisplayProgressBar("Generate Bytes", name, 1.0f * sheetCount / sheetDict.Count);

            //Dictionary<int, Type> mapCellInfoDic = new Dictionary<int, Type>();
            var rows = data.Rows.Count;
            var listname = $"Table.{name}array" ;
            Assembly assembly = Assembly.Load("HotUpdate");
            Type typelist = assembly.GetType(listname);

            if (typelist == null)
            {
                Debug.Log("出问题了！！！");
                EditorUtility.ClearProgressBar();
                return;
            }

            Table.Examplearray asd = new Table.Examplearray();

          
            var listObj = Activator.CreateInstance(typelist);
            if(listObj==null)
            {
                Debug.Log("实例化失败");
                EditorUtility.ClearProgressBar();
                return;
            }
         

            var list = listObj.GetType().GetProperty("Rows").GetValue(listObj);
            var addMethod = list.GetType().GetMethod("Add");
            Type type1 = assembly.GetType($"Table.{name}" );
            var cols = data.Columns.Count;
                for (var i = 4; i < rows; i++)
                {

                    var obj = Activator.CreateInstance(type1);
            
                    var type = obj.GetType();
                    for (var j = 0; j < cols; j++)
                    {
                        var row0 = data.Rows[0][j].ToString();
                        if (!FilterKey(row0, "client")) continue;
                        var row1 = data.Rows[1][j].ToString();
                        var row2 = data.Rows[2][j].ToString();
                        var value = data.Rows[i][j];
                        if (row1.StartsWith("array"))
                        {
                            var reg = new Regex("<(.*)>");
                            var match = reg.Match(row1);
                            var valueType = match.Groups[1].Value;
                            var arrayValue = obj.GetType().GetProperty(row2+"s").GetValue(obj);
                            var valueStr = value.ToString();
                            var valueList = valueStr.Split('#');
                            for (var k = 0; k < valueList.Length; k++)
                            {
                                switch (valueType)
                                {
                                    case "int":
                                        ((List<int>)arrayValue).Add(Convert.ToInt32(valueList[k]));
                                        break;
                                    case "float":
                                        ((List<float>)arrayValue).Add(Convert.ToSingle(valueList[k]));
                                        break;
                                    case "string":
                                        ((List<string>)arrayValue).Add(valueList[k]);
                                        break;
                                    case "bool":
                                        ((List<bool>)arrayValue).Add(Convert.ToBoolean(valueList[k]));
                                        break;
                                }
                            }
                        }
                      
                        else
                        {
                            SetValue2(type, row1, row2, obj, value, i, j, name);
                        }
                    }

                    addMethod.Invoke(list, new object[] { obj });
                }
              
                var outFile = string.Format(OUTSHEETBYTES_client, name);
                if (Base.Utils.FileUtil.CheckFileAndCreateDirWhenNeeded(outFile))
                {
                    
                    Save(outFile, listObj);
                }
            }
            Debugger.Log("Generate Bytes Done!");
     
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }

    public static void Save<T>(string outFile, T request)
    {
        var buffer = ProtobufUtil.NSerialize(request);
        File.WriteAllBytes(outFile, buffer);
    }
    public void Export(string outFile)
    {
        using (MemoryStream m = new MemoryStream())
        {
            Serializer.Serialize(m, this);
            m.Position = 0;
            int length = (int)m.Length;
            var buffer = new byte[length];
            m.Read(buffer, 0, length);
            File.WriteAllBytes(outFile, buffer);
        }
    }
}
